<?php
namespace MS;

use Security\DES;
use Yaf\Registry;
use Wxxiong6\WxxLogger\WxxLogger as Log;

/**
 * @desc 恒昌利通--坤源投资调用金证敏识的api,通过MD5withRsa和Rsa加密算法实现
 */
class Minsh
{
    public static function loadConfig()
    {
        return Registry::get('config')['ms'];
    }

    public static function getMsIdPhotoData($fileName)
    {
        try {
            $config = self::loadConfig();

            $url = $config['ocrUrl'];
            if (substr($url, -1) === ',') {
                $url = substr($url, 0, -1);
            }
            $post_head [] = "merchantID:" . $config['merchantID'];
            $post_head [] = "account:".$config['account'];
            $post_head [] = "timeStamp:" . self::encrypt(self::getMillisecond(), $config['key']);

            if (!is_file($fileName)) {
                return [];
            }

            $str = file_get_contents($fileName);
            Log::write("minshi: start".$url);
            $searchResult = self::curlPost($url, $str, $post_head);
            Log::write("minshi: return".$searchResult);
            $resultArr = explode("\n", $searchResult);
            $responseBody = array_pop($resultArr);
            $responseJson = self::decrypt($responseBody, $config['key']);
            $responseArr = json_decode($responseJson, true);
            return $responseArr;
        } catch (\Exception $e) {
            Log::write("minshi2 error :".$e->getMessage());
        }

        return [];
    }

    public static function getMillisecond()
    {
        $time = microtime(true);
        return round($time * 1000);
    }

    public static function curlPost($url, $post_data, $post_head = 0, $timeout = 30)
    {
        if (!empty($post_data) && is_array($post_data)) {
            $post_data = http_build_query($post_data);
        }
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_HEADER, 1) ;
        curl_setopt($ch, CURLOPT_HTTPHEADER, $post_head) ;
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:31.0) Gecko/20100101 Firefox/31.0");
        //为了支持cookie
        curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookie.txt') ;
        curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
        curl_setopt($ch, CURLOPT_NOSIGNAL, 1);    //注意，毫秒超时一定要设置这个
        curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLINFO_HEADER_OUT, false);
        $result = curl_exec($ch);
        try {
            if ($result === false) {
                throw new \Exception(curl_error($ch));
            }
        } catch (\Exception $e) {
            throw new \Exception($e->getMessage());
        }
        curl_close($ch);
        return $result;
    }

    public static function  encrypt($input, $key)
    {
        $size = mcrypt_get_block_size('des', 'ecb');
        $input = self::pkcs5_pad($input, $size);

        $td = mcrypt_module_open('des', '', 'ecb', '');
        $iv = @mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
        @mcrypt_generic_init($td, $key, $iv);
        $data = mcrypt_generic($td, $input);
        mcrypt_generic_deinit($td);
        mcrypt_module_close($td);
        $data = base64_encode($data);
        return $data;
    }

    public static function decrypt($encrypted, $key)
    {
        $encrypted = base64_decode($encrypted);
        $td = mcrypt_module_open('des', '', 'ecb', '');
        // 使用MCRYPT_DES算法,cbc模式
        $iv = @mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
        $ks = mcrypt_enc_get_key_size($td);
        @mcrypt_generic_init($td, $key, $iv);
        // 初始处理
        $decrypted = mdecrypt_generic($td, $encrypted);
        // 解密
        mcrypt_generic_deinit($td);
        // 结束
        mcrypt_module_close($td);
        $y = self::pkcs5_unpad($decrypted);
        return $y;
    }

    protected static function pkcs5_pad($text, $blocksize)
    {
        $pad = $blocksize - (strlen($text) % $blocksize);
        return $text . str_repeat(chr($pad), $pad);
    }

    protected static function pkcs5_unpad($text)
    {
        $pad = ord($text{strlen($text) - 1});
        if ($pad > strlen($text))
            return false;
        if (strspn($text, chr($pad), strlen($text) - $pad) != $pad)
            return false;
        return substr($text, 0, - 1 * $pad);
    }

    public static function doFaceCheck($uid, $pid, $facePhoto, $facePhotoUrl)
    {
        $userMs = \UserMSModel::getPassedByUid($uid);
        if (!$userMs) {
            return '请先上传身份证照片';
        }
        $private = \UserPrivateModel::findByUidAndPid($uid, $pid);
        if (!$private) {
            return '流程有问题';
        }

        $failRecords = \UserVerifaceRecordModel::getUsedCnt($uid, $pid);
        if ($failRecords >= 20) {
            $private->fill(['private_reserve_status' => 5,'update_time' => date('Y-m-d H:i:s')]);
            $private->save();

            return 5;
        }

        if (!file_exists($facePhoto)) {
            return '请先拍照';
        }

        $userArr = \UserModel::query()->find($uid);
        $idPhoto = $userMs->getRealFrontImgPath();
        $idBackPhoto = $userMs->getRealBackImgPath();
        $minshiConfig = self::loadConfig();

        $minshiVerifyUrl = $minshiConfig['verifyUrl'];

        $post_head = [];
        $post_head [] = "merchantID:".$minshiConfig['merchantID'];
        $post_head [] = "account:".$minshiConfig['account'];
        $post_head [] = "timeStamp:" . self::encrypt(self::getMillisecond(), $minshiConfig['key']);

        $face_body['databaseImageContent'] = base64_encode(file_get_contents($idPhoto));
        $face_body['databaseImageType'] = 2; // 使用身份证照片传2  使用网纹照传1
        $face_body['queryImageContent'] = base64_encode(file_get_contents($facePhoto));
        $encrypt_face_body = self::encrypt(json_encode($face_body), $minshiConfig['key']);

        $verifyresult = self::curlPost($minshiVerifyUrl, $encrypt_face_body, $post_head);
        $resultArr = explode("\n", $verifyresult);
        $responseBody = array_pop($resultArr);
        $responseJson = self::decrypt($responseBody, $minshiConfig['key']);
        Log::info("[verifyUrl:接收] ".$responseJson);
        $responseArr = json_decode($responseJson, true);
        if (empty($responseArr)) {
            return '第三方Verify接口异常';
        }

        $score = isset($responseArr['pairVerifySimilarity'])?
            floor($responseArr['pairVerifySimilarity']):0;

        $record = new \UserVerifaceRecordModel();
        $record->setRawAttributes(
            [
                'uid' => $uid,
                'pid' => $pid,
                'score' => $score,
                'photo_path' => $facePhotoUrl,
                //'auth_source' => '',
                'auth_result' => 1,
                'create_time' => date('Y-m-d H:i:s'),
                'img_path_front'=>$userMs->img_path_front,
                'img_path_reverse'=>$userMs->img_path_reverse,
                'username'=>$userArr->username,
                'identity_id'=>$userArr->identity_id
            ]
        )->save();

        if (!empty($responseArr) && $responseArr['rtn'] == 0) {
            $authResult = \VerifaceRuleModel::getAuthStatus($score);

            if ($authResult == 3) { // 3 通过
                $rows = $private->fill(['private_reserve_status' => 6,'update_time' => date('Y-m-d H:i:s')])
                    ->save();
                $record->fill(['auth_result' => 3])->save();
                if ($rows > 0) {
                    return 3;
                }
            } elseif ($authResult == 2) { // 2 疑似
                $rows = $private->fill(['private_reserve_status' => 3,'update_time' => date('Y-m-d H:i:s')])
                    ->save();
                $record->fill(['auth_result' => 2])->save();
                if ($rows > 0) {
                    return 2;
                }
            } elseif ($authResult == 1) { // 不通过
                $failRecords = \UserVerifaceRecordModel::getUsedCnt($uid, $pid);
                if ($failRecords >= 20) {
                    $private->fill(['private_reserve_status' => 5,'update_time' => date('Y-m-d H:i:s')]);
                    $private->save();

                    return 5;
                } else {
                    $private->fill(['private_reserve_status' => 2,'update_time' => date('Y-m-d H:i:s')]);
                    $private->save();

                    return 1;
                }

            }
            return '没有对应的判定规则';
        } elseif (!empty($responseArr) && $responseArr['rtn'] != 0) {
            return $responseArr['message'];
        } else {
            return '第三方接口对照异常';
        }
    }
}